package cn.edu.cug.cs.gtl.renders.openinventor.basics;

import cn.edu.cug.cs.gtl.apis.render.basics.Line;
import cn.edu.cug.cs.gtl.apis.render.basics.Matrix;
import cn.edu.cug.cs.gtl.apis.render.basics.Plane;
import cn.edu.cug.cs.gtl.apis.render.basics.Vec3f;
import com.openinventor.inventor.SbLine;
import com.openinventor.inventor.SbMatrix;
import com.openinventor.inventor.SbPlane;
import com.openinventor.inventor.SbVec3f;

public class PlaneImpl implements Plane {
    protected SbPlane nativeObject = null;


    public PlaneImpl(){
        this.nativeObject= new SbPlane();
    }

    public PlaneImpl(SbPlane plane){
        this.nativeObject=plane;
    }

    public  PlaneImpl(Vec3f p0, Vec3f p1, Vec3f p2) {
        nativeObject = new SbPlane(
                (SbVec3f) p0.getNativeObject(),
                (SbVec3f)p1.getNativeObject(),
                (SbVec3f)p2.getNativeObject());
    }


    public  PlaneImpl(Vec3f normal, Vec3f point) {
        nativeObject = new SbPlane(
                (SbVec3f) normal.getNativeObject(),
                (SbVec3f) point.getNativeObject()
        );
    }

    @Override
    public Object getNativeObject() {
        return this.nativeObject;
    }

    @Override
    public boolean attach(Object nativeObject) {
        if(nativeObject instanceof SbPlane){
            this.nativeObject = (SbPlane) nativeObject;
            return true;
        }
        return false;
    }

    @Override
    public Object detach() {
        SbPlane r = this.nativeObject;
        this.nativeObject=null;
        return r;
    }


    /**
     * Returns the distance from a point to plane.
     *
     * @param point
     * @return
     */
    @Override
    public float getDistance(Vec3f point) {
        return nativeObject.getDistance((SbVec3f) point.getNativeObject());
    }

    /**
     * Returns distance from origin to plane.
     *
     * @return
     */
    @Override
    public float getDistanceFromOrigin() {
        return nativeObject.getDistanceFromOrigin();
    }

    /**
     * Returns normal vector to plane.
     *
     * @return
     */
    @Override
    public Vec3f getNormal() {
        return new Vec3fImpl(nativeObject.getNormal());
    }

    @Override
    public float[] getValue() {
        return nativeObject.getValue();
    }

    /**
     * Intersect line and plane, returning true if there is an intersection, false if line is parallel to plane.
     *
     * @param l
     * @return
     */
    @Override
    public Vec3f intersect(Line l) {
        return new Vec3fImpl(
                this.nativeObject.intersect((SbLine)(l.getNativeObject()))
        );
    }

    /**
     * Returns true if the given point is within the half-space defined by the plane.
     *
     * @param point
     * @return
     */
    @Override
    public boolean isInHalfSpace(Vec3f point) {
        return nativeObject.isInHalfSpace((SbVec3f) point.getNativeObject());
    }

    /**
     * Offset a plane by a given distance.
     *
     * @param d
     */
    @Override
    public void offset(float d) {
        nativeObject.offset(d);
    }

    @Override
    public Plane setValue(float[] components) {
        return new PlaneImpl(nativeObject.setValue(components));
    }

    @Override
    public Plane setValue(float[] components, int startIndex) {
        return new PlaneImpl(nativeObject.setValue(components,startIndex));
    }

    @Override
    public void setValue(Plane copyFrom) {
        nativeObject.setValue((SbPlane) copyFrom.getNativeObject());
    }

    /**
     * Transforms the plane by the given matrix.
     *
     * @param matrix
     */
    @Override
    public void transform(Matrix matrix) {
        nativeObject.transform((SbMatrix) matrix.getNativeObject());
    }

    @Override
    public void reset(Vec3f p0, Vec3f p1, Vec3f p2) {
        SbPlane plane = new SbPlane(
                (SbVec3f) p0.getNativeObject(),
                (SbVec3f)p1.getNativeObject(),
                (SbVec3f)p2.getNativeObject());
        nativeObject.setValue(plane);
    }

    @Override
    public void reset(Vec3f normal, Vec3f point) {
        SbPlane plane = new SbPlane(
                (SbVec3f) normal.getNativeObject(),
                (SbVec3f) point.getNativeObject()
        );
        nativeObject.setValue(plane);
    }

    @Override
    public void reset(Vec3f normal, float distance) {
        SbPlane plane = new SbPlane(
                (SbVec3f) normal.getNativeObject(),
                distance
        );
        nativeObject.setValue(plane);
    }


}
